<template>
    <vxe-upload ref="uploadRef" show-download-button :download-method="downloadMethod" v-model="fileList"
        :upload-method="uploadMethod" :file-types="fileTypes" :limit-size="limitSize" @remove="remove"
        :disabled="disabled" :readonly="readonly" show-progress></vxe-upload>
</template>

<script>
import { uploadFile, getFileLimit, getFileInfo } from '@/api/upload'

export default {
    props: {
        // 文件模块
        module: String,
        // 文件 fileId/path
        fileId: String,
        // 保持类型：fileId/path
        saveType: {
            type: String,
            default: 'fileId'
        },
        disabled: Boolean,
        readonly: Boolean,
    },
    model: {
        prop: 'fileId',
        event: 'input'
    },
    data() {
        return {
            fileList: [],
            limitSize: 0,
            fileTypes: [],
        }
    },
    watch: {
        module: {
            immediate: true,
            handler(newVal) {
                if (newVal) {
                    this.setFileLimit()
                }
            }
        },
        fileId: {
            immediate: true,
            handler(newVal) {
                if (newVal) {
                    this.setFileList();
                }
            }
        }
    },
    methods: {
        async sleep(time) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve()
                }, time)
            })
        },
        /**
         * 异步上传文件方法
         * 
         * 此方法使用上传文件的API，将选定的文件上传到服务器，并在上传成功后处理响应结果
         * 它不仅更新组件内部的状态，还通过'success'事件向父组件报告上传成功的文件信息
         * 
         * @param {Object} param0 包含待上传文件信息的对象
         * @param {File} param0.file 要上传的文件对象，通常由文件输入框或拖拽事件获得
         */
        async uploadMethod({ file, updateProgress }) {

            try {
                let progress = 0;

                const timer = setInterval(() => {
                    progress += 7
                    if (progress > 90) {
                        updateProgress(99)
                    } else {
                        updateProgress(progress)
                    }
                }, 300)
                const res = await uploadFile(file, this.module)
                clearInterval(timer);

                const { fileId, path } = res;
                if (this.saveType == 'fileId') {
                    this.$emit('input', fileId)
                } else {
                    this.$emit('input', path)
                }
                this.$message.success('上传成功')
                this.$emit('success', res)
            } catch (err) {
                clearInterval(timer);
            }
            return true;
        },
        async setFileList() {
            if (this.saveType == 'fileId') {
                const res = await getFileInfo(this.fileId)
                if (res) {
                    this.fileList = [
                        {
                            name: res.fileName,
                            url: this.FILE_BASE_URL + res.filePath,
                        }
                    ]
                }
            } else {
                const lastSlash = this.fileId.lastIndexOf('/');
                const fileName = lastSlash >= 0 ? this.fileId.slice(lastSlash + 1) : this.fileId;
                this.fileList = [
                    {
                        name: fileName,
                        url: this.FILE_BASE_URL + this.fileId,
                    }
                ]
            }
        },
        async setFileLimit() {
            if (this.readonly) {
                return
            }
            const { fileUploadExtLimit, fileUploadMaxSize } = await getFileLimit(this.module);
            this.fileTypes = fileUploadExtLimit.split(',')
            this.limitSize = +fileUploadMaxSize / 1024 / 1024
        },
        remove(e) {
            this.$emit('input', '')
        },
        async downloadMethod({ option }) {

            try {
                const blob = await fetch(option.url).then(response => response.blob())
                await this.VxeUI.saveFile({
                    filename: option.name,
                    content: blob
                })
                this.$message.success('下载成功')
            } catch (e) {
                this.$message.error('下载失败')

                console.error(e)
            }
        }
    },
    mounted() {
        if (!this.readonly) {
            this.$refs.uploadRef.$el.getElementsByClassName('vxe-button--content')[0].innerText = '点击上传'
        }
    }

}
</script>

<style lang="scss" scoped></style>